#!/usr/sbin/rsct/perl5/bin/perl 
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 1999,2002 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# "@(#)01   1.22   src/rsct/registry/cli/bin/chsrcoldv.perl, srcli, rsct_rpyxh, rpyxht1f3 2/22/01 16:25:39"
######################################################################
#                                                                    #
# Module: chsrcoldv                                                  #
#                                                                    #
# Purpose:                                                           #
#   chsrcoldv - Changes one or more default values in a System       #
#               Registry table.                                      #
#                                                                    #
# Syntax:                                                            #
#  To change column default values using command line input:         #
#   chsrcoldv  [-h][-TV] Table Column=Default_value ...              #
#                                                                    #
#  To change column default values using an input file:              #
#   chsrcoldv  [-h][-TV] -f System_Registry_Input_File Table         #
#                                                                    #
# Flags:                                                             #
#   -h  Help - writes this command's usage statement to stdout       #
#   -f System_Registry_Input_File                                    #
#       File input. Instead of command line data, use an input file  #
#       containing names of tables to be altered including           #
#       descriptions of columns to be added to the new table. Format #
#       is listed under Description.                                 #
#   -T  Trace - -writes this program's trace messages to stderr      #
#   -V  Verbose - writes this program's verbose messages to stderr   #
#                                                                    #
# Operands:                                                          #
#   Table   The name of the table that you wish to modify. The Table #
#           operand may contain a relative or absolute path name.    #
#   Column  The name of the column for which you wish to change the  #
#           default value. The Column must match one of the column   #
#           names previously defined in this tables' metadata.       #
#   Default_value The new default value to be assigned to this       #
#           column. This value will be treated to be of the same data#
#           type as the given column.                                #
#            One or more Column=Default_value pairs can be specified.#
#                                                                    #
# Description:                                                       #
#   The chsrcoldv command allows you to change one or more default   #
#   values for a given System Registry table.  Using multiple        #
#   Column_name=New_default_value pairs is equivalent to calling the #
#   routine once for every pair.                                     #
#                                                                    #
#   You must have metadata permission on the table to perform this   #
#   operation.  TODO: Security will be better defined when it is     #
#   available for the registry. ( Feature 48402 )                    #
#                                                                    #
#   Resource handles are entered as hexadecimal, using the format    #
#       (including quotes):                                          #
#       "0x######## 0x######## 0x######## 0x######## 0x########"     #
#   where '########' is a hexadecimal number. If more than 5         #
#   numbers are given, only the first 5 will be used. If less than   #
#   5 are given, 0x00000000 will be placed in the missing places.    #
#                                                                    #
#   Binary data is entered as hexadecimal, using the format          #
#       (including quotes):                                          #
#       "0x######## 0x######## 0x######## ...."    -OR-              #
#       "0x################...."                                     #
#   where '########' is a hexadecimal number. The length of the      #
#   hexadecimal string is not significant (each number could be      #
#   more or less than 8 digits). Values are stored as                #
#   given in the System Registry (the leading 0x is stripped off     #
#   for storage.)                                                    #
#                                                                    #
#   Long and unsigned long (64 bit) are expected in decimal format.  #
#                                                                    #
#   Strings with spaces need to be enclosed in quotes.               #
#                                                                    #
#   For more information on entering the data types, please refer to #
#   the srcli man page and the chsrcoldv man page.                   #
#                                                                    #
#   Column definition data (metadata) for a new table goes in a flat #
#   text file in a stanza headed by the keyword 'DataChanges::' :    #
#       DataChanges::                                                #
#       chsrcoldv:                                                   #
#           column = default_value                                   #
#           column = default_value                                   #
#           column = default_value                                   #
#                                                                    #
#   The tab at the beginning of each line is provided here for       #
#   readability but is not necessary in the input file. If more than #
#   one DataChanges stanza exists in the input file, only the first  #
#   will be read in.                                                 #
#                                                                    #
# Exit Values:                                                       #
#   0  SR_CLI_SUCCESS        Command completed successfully.         #
#   1  SR_CLI_REGISTRY_ERROR Command terminated due to an underlying #
#                            System Registry error.                  #
#   2  SR_CLI_ERROR          Command terminated due to an underlying #
#                            error in the command script.            #
#   3  SR_CLI_BAD_OPERAND    Command terminated due to user          #
#                            specifying a bad operand.               #
#   4  SR_CLI_BAD_FLAG       Command terminated due to user          #
#                            specifying an invalid flag.             #
#   5  SR_CLI_USER_ERROR     Command terminated due to a user error. #
#                            For example specifying an undefined     #
#                            directory to be listed.                 #
#                                                                    #
# Examples:                                                          #
#   chsrcoldv /samples/table1 column1=10 column2=12.5                #
#                                                                    #
#   chsrcoldv /samples/table2 Name='N/A'                             #
#                                                                    #
#   chsrcoldv /samples/table3 Handle="12345678 abcdefab 00000000     #
#              a2a2a2a2 00000000" LongColumn=98734321546432564       #
#   Note: the previous example has the resource handle split onto    #
#   two lines for readability.                                       #
#                                                                    #
#--------------------------------------------------------------------#
# Inputs:                                                            #
#                                                                    #
# Outputs:                                                           #
#   stdout - messages during execution and Verbose output            #
#   stderr - error messages                                          #
#                                                                    #
# External Ref:                                                      #
#                                                                    #
#   Commands: $LSMSG                                                 #
#   Extensions:  CT::SR.pm CT::CT.pm CT::SRrc.pm                     #
#   Perl library routines: Getopts::Std                              #
#   SR cli routines: : SR_cli_utils.pm - init_session, isRelative    #
#                                   clean_session, printCEMsg        #
#                                    set_session_variables           #
#                                                                    #
# Tab Settings:                                                      #
#   4 and tabs should be expanded to spaces before saving this file. #
#   in vi:  (:set ts=4  and   :%!expand -4)                          #
#                                                                    #
# Change Activity:                                                   #
#   000929 HGJ 38317: Initial delivery.                              #
######################################################################

#--------------------------------------------------------------------#
#                                                                    #
# General Program Flow/Logic:                                        #
#                                                                    #
# A: Parse command line - get table name and input file              #
# B: Initialise session with registry, including changing the        #
#    current directory if a relative path name is given (use value   #
#    given in CT_SR_HOME)                                            #
# C: Open file to be edited - exit if it won't open                  #
# D: Parse the input data - make a call to SR::get_table_metadata    #
#    in order to check the column types and properly assign the      #
#    field data to be passed to SR::change_default_value             #
# E: Call CT::SR::change_default_value for every column listed       #
# F: Close session table and tree                                    #
#                                                                    #
#--------------------------------------------------------------------#

#--------------------------------------------------------------------#
# Included libraries and extensions                                  #
#--------------------------------------------------------------------#
use lib "/usr/sbin/rsct/pm";
use locale;
use Getopt::Std;

use CT::CT qw(:ct_data_type_t);
use CT_cli_utils qw(printIMsg
                    printEMsg
);
use CT_cli_input_utils qw(convert_input_value 
                          process_cmdline_input
                          process_input_file
);

use CT::SR;
use CT::SRrc;
use CT::SR qw(:sr_qualifier_t);
use SR_cli_utils qw(init_session 
                    isRelative 
                    printCEMsg 
                    printCIMsg 
                    $DEFAULT_GLOBAL_MOUNT_POINT 
                    get_table_metadata
                    free_table_metadata
                    open_table
                    clean_session
                    set_session_variables
                    error_exit
); 
use SR_cli_rc qw(:return_codes);


#--------------------------------------------------------------------#
# Global Variables                                                   #
#--------------------------------------------------------------------#
# Constants for use throughout the program
$TRUE           = 1;
$FALSE          = 0;

# For parsing the command line
$Set_work_dir   = $FALSE;
$Command_line_input = "";
$Verbose        = $FALSE;
$Trace          = $FALSE;

$Opt_File_Input = $FALSE;                 # default - see -f (file)

# Messaging variables
$PROGNAME       = "chsrcoldv";
$MSGCAT         = "srcli.cat";
$CTDIR          = "/usr/sbin/rsct";       # Cluster directory path
$CTBINDIR       = "$CTDIR/bin";           # Cluster Bin directory path
$LSMSG          = "$CTBINDIR/ctdspmsg";   # display message rtn.
$ENV{'MSGMAPPATH'} = "$CTDIR/msgmaps";    # Msg maps used by $LSMSG  

%Cleanup = ();                            # Hash of items to cleanup
                                          # {Session} $session to term

#--------------------------------------------------------------------#
# Variables                                                          #
#--------------------------------------------------------------------#
# Variables for use with extensions
my $Table_handle   = CT::SR::table_handle_t->new();
my $Tree_handle    = "";                  # initialised in initSession

# Other variables
my $rc             = 0;                   # assume good return code
my $Table_name     = "";
my $Table          = "";
my $filename       = "";
my @Columns        = ();
my $Mount_point    = $DEFAULT_GLOBAL_MOUNT_POINT;


#--------------------------------------------------------------------#
# Main Code                                                          #
#--------------------------------------------------------------------#
# TODO: Many verbose statements in this program are to be future trace
# statements when the facility becomes available to the SR. 
# ( Feature 48401 )

# Parse the command line, exit if there are errors
($rc, $Table_name, $filename, @Columns) = parse_cmd_line();  
($rc == 0) || error_exit($rc);

if ($Verbose) {
    $Command_line_input .= "  $Table_name\n";
    foreach (@Columns) { $Command_line_input .= "  $_\n"; }
    $Command_line_input = '"'.$Command_line_input.'"';
    printIMsg("IMsgchsrcoldvCommandLineInput", $Command_line_input);
}


# Initialize Registry Library Connection
($Set_work_dir, $Table) = set_session_variables($Table_name);
($rc, $Tree_handle) = init_session($Set_work_dir);

# Check the error code and exit if necessary
($rc == 0) || error_exit($rc);

# Add the tree handle to the cleanup hash
$Cleanup{Session} = $Tree_handle;


if ($Opt_File_Input) {
    ($rc, $Column_data) = process_input_file($filename, 
                            "DataChanges");
} 
else {  
    ($rc, $Column_data) = process_cmdline_input(\@Columns);
}
($rc == 0) || error_exit($rc);


$Verbose && printIMsg("IMsgchsrcoldvTableName", $Table_name, $Table);

# Open table for the session
($rc, $Table_handle) = open_table($Tree_handle, $Table, 
                        $Table_name, SR_METADATA);
($rc == 0) || error_exit($rc);

# Add the table handle to the cleanup hash
push @{$Cleanup{Tables}} , $Table_handle;


# Call subroutine to change the default values
# Error messaging handled within the subroutine
$Trace && print STDERR "Entering sub change_values\n";

$rc = change_values($Table_handle, $Table_name, $Column_data);

$Trace && print STDERR "Exiting sub change_values, rc $rc\n";

($rc == 0) || error_exit($rc);

$rc = clean_session($Tree_handle, $Mount_point, $Table_handle);

# Clear the cleanup hash before final error check
%Cleanup = ();
($rc == 0) || error_exit($rc);

# Return code is 0 if code reaches this point
exit $rc;

#--------------------------------------------------------------------#
# End Main Code                                                      #
#--------------------------------------------------------------------#


#--------------------------------------------------------------------#
# change_values:                                                     #
#   Uses SR:change_default_value on each line of input in the        #
#   input array @columns.                                            #
#                                                                    #
# Parameters:                                                        #
#   $table_handle   - table handle to be worked with                 #
#   $table_name     - name of the table to be worked with            #
#   @columns        - input array containing column name/default     #
#                     value pairs                                    #
#                                                                    #
# Return values:                                                     #
#   $local_rc       - return code value from                         #
#                       CT::SR::change_default_value                 #
#                                                                    #
#--------------------------------------------------------------------#
sub change_values
{
# Grab the input parameters
my $table_handle = shift;
my $table_name = shift;
my $columns = shift;

# Set up local variables
my $local_rc = 0;
my $worst_rc = 0;
my $name = "";
my $default_value = "";
my $quit = $FALSE;
my @values = ();

($local_rc, $metadata) = get_table_metadata($table_handle);
if ($local_rc != 0) { return $local_rc; }

my $col_defs = $metadata->getColumnDefs;

my $data = $columns->[0][1];
my $values;

foreach $row ( @$data ) {

    # Parse out the column name and value.
    # Each line is guaranteed to be in the correct form as 
    # the syntax was checked in parse_cmd_line.
    $name = $row->[0];
    $default_value = $row->[1];

    # Get column type so new data load can be done.

    foreach $entry (@$col_defs) {
        if ($entry->{name} eq $name) {
            ($local_rc, $values->{value}) = convert_input_value( 
                        $entry->{type}, $default_value, 
                        $entry->{sd_defn}->[1]);
            $values->{type} = $entry->{type};
            last;
        }
    }
                        

    if ($local_rc != 0) {   
        printCEMsg("EMsgSRcliInvalidColumnData");
        return SR_CLI_BAD_OPERAND;
    }


    $Verbose && printIMsg("IMsgchsrcoldvChangingValue", $name);

    $Trace && print STDERR "calling CT::SR::change_default_value $name=$default_value\n";
    $local_rc = CT::SR::change_default_value($table_handle, $name, 
                            $values);
    $Trace && print STDERR "CT::SR::change_default_value return code: $local_rc\n";

    ($local_rc, $quit) = error_check("sr_change_default_value",
        $local_rc, $table_name, $name);

    # Clear the memory used for the column and field lists 

    # If the last rc was bad enough we need to quit just return 
    # that rc.
    ($quit) && return $local_rc;

    # Store the least non-zero error code
    if ($worst_rc == 0) { $worst_rc = $local_rc; }  
    elsif ($worst_rc < local_rc) { $worst_rc = $local_rc; }

    $values = {};

} # end foreach (@_)

$local_rc = free_table_metadata($metadata);

($worst_rc > 0) ?  return $worst_rc : return $local_rc;
}   # end change_values


#--------------------------------------------------------------------#
# parse_cmd_line:                                                    #
#   Uses getopts() to grab flags on the command line, pick up the    #
#   input data and do a rough parse on it to make sure the overall   #
#   syntax is correct.  Print the usage statement if -h flag is      #
#   specified, and exit immediately.                                 #
#                                                                    #
# Return values:                                                     #
#   $local_rc - local return code.                                   #
#   $table_name - table name to be added.                            #
#   $filename - input filename.                                      #
#   @columns - array of column name=default value pairs from         #
#              the input data.                                       #
#                                                                    #
# Global Variables Modified:                                         #
#   $Opt_File_Input    output   True (-f) using input file.          #
#   $Trace             output   True (-T) turn Trace mode on.        #
#   $Verbose           output   True (-V) turn Verbose mode on.      #
#--------------------------------------------------------------------#
sub parse_cmd_line
{
# Set up local variables
my $local_rc = 0;
my @columns = ();
my $table_name = "";
my $filename = "";
my %opts = ();

if (getopts('hf:TV', \%opts) == 0) {   # parse input flags
    # Return Error parsing flags - add a message here, too.
    printCEMsg("EMsgSRcliInvalidFlag");
    print_usage();
    return SR_CLI_BAD_FLAG;
}                  

if (defined $opts{h}) {   # print usage and exit
    print_usage();
    exit(0);    # exit quickly
}

# Get table name from input.
$table_name = shift @ARGV;
if ((!$table_name ) || ($table_name =~ /=/)) {
    printCEMsg("EMsgSRcliNoTableName");
    print_usage();
    return SR_CLI_BAD_OPERAND;
}

if (defined $opts{f}) {
    $Opt_File_Input = $TRUE;
    $filename = $opts{f};
    if ($#ARGV >= 0) {
        # Print too many operands message
        printCEMsg("EMsgSRcliTooManyOperands");
        print_usage();
        return SR_CLI_BAD_OPERAND;
    }
}

# Make sure Column=Default_value... pairs are specified on
# the command line if the -f flag is not used
if (!defined $opts{f}) {
    if ($#ARGV < 0) {
        printCEMsg("EMsgSRcliNoColumnData");
        print_usage();
        return SR_CLI_BAD_OPERAND;
    }
    @columns = @ARGV;
}

# Set Trace flag if requested
if (defined $opts{T}) {
    $Trace = $TRUE;
}

# Set Verbose flag if requested
if (defined $opts{V}) {
    $Verbose = $TRUE;
}

return($local_rc, $table_name, $filename, @columns);
}   # end parse_cmd_line


#--------------------------------------------------------------------#
# error_check:                                                       #
#   Checks the return code from the SR function.  If an error is     #
#   detected appropriate error messages will be displayed and        #
#   SR CLI return code set.                                          #
#                                                                    #
# Parameters:                                                        #
#   $sr_function  - Name of the SR function that was called and      #
#                   whose error code we are checking.                #
#   $sr_rc        - SR function return code.                         #
#   $table_name   - Name of the SR table.                            #
#   $column_name  - Column name.                                     #
#                                                                    #
# Return values:                                                     #
#   $rc           - SR C API rc converted to an SR CLI rc.           #
#   $quit         - indication if error severe enough to stop.       #
#                                                                    #
# Global References:                                                 #
#   None.                                                            #
#--------------------------------------------------------------------#
sub error_check
{
my ($sr_function, $sr_rc, $table_name, $column_name) = @_;
my $rc = 0;
my $quit = $FALSE;

if ($sr_rc != 0) {
    if ($sr_rc == SR_NO_COLUMN) {
        printEMsg("EMsgchsrcoldvNoColumn", $column_name, $table_name);
        $rc = SR_CLI_USER_ERROR;
    }        
    elsif ($sr_rc == SR_ILLEGAL_OPERATION) {
        printEMsg("EMsgchsrcoldvIllegalOperation");
        $rc = SR_CLI_USER_ERROR;
    }
    elsif ($sr_rc == SR_NO_TABLE) {
        printCEMsg("EMsgSRcliNoTable");
        $rc = SR_CLI_USER_ERROR;
        $quit = $TRUE;  
    }
    elsif ($sr_rc == SR_NO_PERMISSION) {
        printEMsg("EMsgchsrcoldvNoPermission", $table_name);
        $rc = SR_CLI_USER_ERROR;
        $quit = $TRUE;
    }
    elsif ($sr_rc == SR_CONNECTION_LOST) {
        printCEMsg("EMsgSRcliConnectionLost");
        $rc = SR_CLI_REGISTRY_ERROR;
        $quit = $TRUE;
    }
    else {
        printEMsg("EMsgchsrcoldvErrorChangingDefVal", $column_name);
        printCEMsg("EMsgSRcliSRCommandFailure", $sr_function, $sr_rc);
        $rc = SR_CLI_REGISTRY_ERROR;
        $quit = $TRUE;
    }
}

return ($rc, $quit);
}   # end error_check

#--------------------------------------------------------------------#
# print_usage : print the usage statement (syntax) to stdout.        #
#   See this command's prologue syntax section for current usage.    #
#--------------------------------------------------------------------#
sub print_usage
{
printIMsg("IMsgchsrcoldvUsage");
}   # end print_usage


#--------------------------------------------------------------------#
# End File                                                           #
#--------------------------------------------------------------------#
